package org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.futbolista.habilidad;

import java.util.ArrayList;

import org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.futbolista.Futbolista;
import org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.futbolista.FutbolistaBase;
import org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.util.Balon;
import org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.util.PaseAlto;
import org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.util.PosicionCampo;

/**
 * @author Joan Crosas
 *
 */
public class PaseOfensivo extends HabilidadConBalon {
	public enum ExactitudPase {
		CORTO,
		LARGO
	}
	
	public enum EfectividadPase {
		RECIBIDO,
		PERDIDO
	}
	
	/**
	 * @param futbolista
	 */
	public PaseOfensivo(Futbolista futbolista) {
		super(futbolista);
	}

	@Override
	public boolean ejecutar() {
		if( futbolista.getVisionPartido().futbolistaBalonControlado() == futbolista && 
				futbolista.getIteracionesParaRematar() % 3 == 0 && 
				( !( futbolista.getVisionPartido().saco() && futbolista.getIteracionesParaRematar() == 0 ) ||
				( futbolista.getVisionPartido().saco() && futbolista.getVisionPartido().iteracionesSaque() % 3 == 0 ) ) ) {
			
			ArrayList<Futbolista> futbolistas = futbolista.getVisionPartido().getFutbolistas();
			Balon balon = null;
			for( int i = 0; i < futbolistas.size(); i++ ) {
				balon = evaluarPase( futbolistas.get( i ) );
				if( balon != null ) {
					return true;
				}
			}
		}
		
		return false;
	}
	
	private Balon evaluarPase( Futbolista futbolistaDestino ) {
		// descartamos los que no nos interesan
		if( futbolista == futbolistaDestino ||
				futbolista.getPosicion().distancia( futbolistaDestino.getPosicion() ) > FutbolistaBase.DISTANCIA_MAX_PASE ||
				futbolista.getDistanciaPorteriaRival() < futbolistaDestino.getDistanciaPorteriaRival() + futbolista.getDistanciaAvanzadaPase() ) {
			
			return null;
		}
		
		anticipacion = futbolista.getIteracionesParaRematar();
		
		double anguloBase = futbolista.getPosicion().angulo( futbolistaDestino.getPosicion() );
		double anguloPase = 0;
		
		for( int i = 0; i < 3; i++ ) {
			if( i == 0 ) {
				anguloPase = anguloBase + FutbolistaBase.DESVIO_ANGULO_PASE + futbolista.getPrecision() / 2;
				if( futbolista.getPosicion().getX() > futbolistaDestino.getPosicion().getX() ) {
					anguloPase = anguloBase - FutbolistaBase.DESVIO_ANGULO_PASE - futbolista.getPrecision() / 2;
				}
			} else if( i == 1 ) {
				anguloPase = anguloBase + FutbolistaBase.DESVIO_ANGULO_PASE;
				if( futbolista.getPosicion().getX() > futbolistaDestino.getPosicion().getX() ) {
					anguloPase = anguloBase - FutbolistaBase.DESVIO_ANGULO_PASE;
				}
			} else if( i == 2 ) {
				anguloPase = anguloBase - futbolista.getPrecision() / 2;
				if( futbolista.getPosicion().getX() > futbolistaDestino.getPosicion().getX() ) {
					anguloPase = anguloBase + futbolista.getPrecision() / 2;
				}
			}
			
			// comencem amb l'algoritme dels pases			
			ArrayList<PaseAlto> pases = new ArrayList<PaseAlto>();
			PaseAlto paseAlto;
			
			paseAlto = obtenerPaseAlto( futbolistaDestino, anguloPase, 1.00, FutbolistaBase.ANGULO_VERTICAL );
			if( paseAlto != null ) {
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
			}
			
			paseAlto = obtenerPaseAlto( futbolistaDestino, anguloPase, 0.80, FutbolistaBase.ANGULO_VERTICAL );
			if( paseAlto != null ) {
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
			}
			
			paseAlto = obtenerPaseAlto( futbolistaDestino, anguloPase, 0.60, FutbolistaBase.ANGULO_VERTICAL );
			if( paseAlto != null ) {
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
			}
			
			for( int j = 0; j < 9; j++) {
				PaseAlto paseAltoCorto = buscarPaseAlto( pases, ExactitudPase.CORTO );
				PaseAlto paseAltoLargo = buscarPaseAlto( pases, ExactitudPase.LARGO );
				
				double potencia = 1;
				double anguloVertical = FutbolistaBase.ANGULO_VERTICAL;
				
				if( paseAltoCorto != null && paseAltoLargo != null ) {
					potencia = (paseAltoCorto.getPotencia() + paseAltoLargo.getPotencia()) / 2;
					anguloVertical = (paseAltoCorto.getAnguloVertical() + paseAltoLargo.getAnguloVertical()) / 2;
					
					paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, potencia, anguloVertical );
					if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
						return paseAlto.getBalon();
					}
					pases.add( paseAlto );
					
				} else if( paseAltoCorto != null ) {
					potencia = paseAltoCorto.getPotencia();
					anguloVertical = paseAltoCorto.getAnguloVertical();
					
				} else if( paseAltoLargo != null ) {
					potencia = paseAltoLargo.getPotencia();
					anguloVertical = paseAltoLargo.getAnguloVertical();
					
				} else {
					break;
				}
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, getMitadAlta( potencia, 1.0 ), getMitadAlta( anguloVertical, FutbolistaBase.ANGULO_VERTICAL_MAX ) );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, potencia, getMitadAlta( anguloVertical, FutbolistaBase.ANGULO_VERTICAL_MAX ) );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, potencia, getMitad( anguloVertical, FutbolistaBase.ANGULO_VERTICAL_MIN ) );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, getMitadAlta( potencia, 1.0 ), getMitad( anguloVertical, FutbolistaBase.ANGULO_VERTICAL_MIN ) );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, getMitad( potencia, 0.6 ), getMitad( anguloVertical, FutbolistaBase.ANGULO_VERTICAL_MIN ) );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, getMitad( potencia, 0.6 ), anguloVertical );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
				
				paseAlto = obtenerPaseAlto( futbolistaDestino, anguloBase, getMitad( potencia, 0.6 ), getMitadAlta( anguloVertical, FutbolistaBase.ANGULO_VERTICAL_MAX ) );
				if( paseAlto.getEfectividadPase() == EfectividadPase.RECIBIDO ) {
					return paseAlto.getBalon();
				}
				pases.add( paseAlto );
			}
			
		}		
		return null;
	}
	
	private PaseAlto obtenerPaseAlto( Futbolista futbolistaDestino, double angulo, double potencia, double anguloVertical ) {
		double velocidadInicial = potencia * futbolista.getRemate();
		Balon balon = new Balon( futbolista.getPosicion(), angulo, velocidadInicial, anguloVertical );
		
		PaseAlto paseAlto = new PaseAlto();
		paseAlto.setBalon( balon );
		paseAlto.setAnguloVertical( anguloVertical );
		paseAlto.setPotencia( potencia );
		
		// exactitud pase
		PosicionCampo posicionRebote = balon.getPosicionRebote();
		double distanciaRebote = futbolista.getPosicion().distancia( posicionRebote );
		double distanciaDestino = futbolista.getPosicion().distancia( futbolistaDestino.getPosicion() );
		paseAlto.setDistanciaExactitud( Math.abs( distanciaRebote - distanciaDestino ) );
		if( distanciaRebote > distanciaDestino ) {
			paseAlto.setExactitudPase( ExactitudPase.LARGO );
		} else {
			paseAlto.setExactitudPase( ExactitudPase.CORTO );
		}
		
		// efectividad pase
		Balon balonPase = evaluarPase(futbolistaDestino, angulo, potencia, anguloVertical);
		if( balonPase != null ) {
			paseAlto.setEfectividadPase( EfectividadPase.RECIBIDO );
		} else {
			paseAlto.setEfectividadPase( EfectividadPase.PERDIDO );
		}
		
		return paseAlto;
	}
	
	private PaseAlto buscarPaseAlto( ArrayList<PaseAlto> pases, ExactitudPase exactitud ) {
		PaseAlto paseAlto = null;
		for( int i = 0; i < pases.size(); i++ ) {
			if( pases.get(i).getExactitudPase() == exactitud ) {
				if( paseAlto == null ) {
					paseAlto = pases.get(i);
					
				} else if( paseAlto != null && pases.get(i).getDistanciaExactitud() < paseAlto.getDistanciaExactitud() ) {
					paseAlto = pases.get(i);
				}
			}
		}
		if( paseAlto != null ) {
			pases.remove( paseAlto );
		}
		return paseAlto;
	}
	
}
